﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Marmat.Forms;
using Marmat.Foundation;

namespace Marmat.Template.WinForm
{

    /// <summary>
    /// 单选记录窗体的默认实现(分页)
    /// </summary>
    /// <typeparam name="Entity"></typeparam>
    /// <typeparam name="DataSource"></typeparam>
    public partial class SelectionRecordPaginationForm<Entity, DataSource> : Forms.Form, ISelectionRecordPaginationForm<Entity, DataSource>
    {
        /// <summary>
        /// 选择窗体--单选
        /// </summary>
        public SelectionRecordPaginationForm()
        {
            InitializeComponent();
        }


        /// <summary>
        /// 获取或设置窗体的图标。
        /// </summary>
        Icon ISelectionRecordBasicForm.Icon
        {
            get => this.Icon;
            set
            {
                this.Icon = value;
                this.ShowIcon = value != null;
            }
        }

        /// <summary>
        /// 设置需要支持搜索的列。
        /// </summary>
        public List<string> SearchCollection { get; } = new List<string>();

        public Func<Entity, bool> Verify { get; set; }
        /// <summary>
        /// 列构建处理器。
        /// </summary>
        public Action<SelectionRecordColumn> ColumnBuilder { get; set; }

        /// <summary>
        /// 获取或设置是否显示过滤面板。
        /// </summary>
        public bool ShowFilterPanel
        {
            get => !this.splitContainer1.Panel1Collapsed;
            set => this.splitContainer1.Panel1Collapsed = !value;
        }

        /// <summary>
        /// 单元格绘制事件。
        /// </summary>
        public event EventHandler<SelectionRecordFormDrawCellEventArgs> DrawCell;

        /// <summary>
        /// 在计算项高度时执行。
        /// </summary>
        public event EventHandler<SelectionRecordFormItemHeightEventArgs> CalcItemHeight;

        /// <summary>
        /// 数据搜索
        /// </summary>
        public Func<SelectionRecordFormPaginationSearchEventArgs, DataSource> Search { get; set; }

        /// <summary>
        /// 每页显示行数
        /// </summary>
        public int LoadTop { get => this.pageControl1.LoadTop; }

        /// <summary>
        /// 显示列的集合。
        /// </summary>
        public SelectionRecordColumnCollection Columns { get; } = new SelectionRecordColumnCollection();

        /// <summary>
        /// 初始化数据
        /// </summary>
        private void LoadData()
        {
            string filter = this.GetSearchCondition();
            var args = new SelectionRecordFormPaginationSearchEventArgs(filter, this.pageControl1.LoadPage);
            var source = this.Search(args);
            this.pageControl1.TotalCount = args.TotalCount;
            Dictionary<SelectionRecordColumn, Type> columnTypeCollection = new Dictionary<SelectionRecordColumn, Type>();
            if (source is DataTable table)
            {
                table.AcceptChanges();
                foreach (DataColumn column in table.Columns)
                {
                    SelectionRecordColumn item = new SelectionRecordColumn(column.ColumnName, string.IsNullOrEmpty(column.Caption) ? column.ColumnName : column.Caption);
                    columnTypeCollection.Add(item, column.DataType);
                }
            }
            else
            {
                MemberInfo[] members = typeof(Entity).GetMembers();
                foreach (MemberInfo member in members)
                {
                    Type dataType;
                    if (member is FieldInfo field)
                        dataType = field.FieldType;
                    else if (member is PropertyInfo property)
                        dataType = property.PropertyType;
                    else
                        continue;
                    SelectionRecordColumn item = new SelectionRecordColumn(member.Name, null);
                    DescriptionAttribute description = member.GetCustomAttribute<DescriptionAttribute>();
                    if (description != null)
                        item.Caption = description.Description;
                    columnTypeCollection.Add(item, dataType);
                }
            }
            if (this.Columns.Count == 0)
                this.Columns.AddRange(columnTypeCollection.Keys);
            else
            {
                foreach (var column in this.Columns)
                {
                    if (string.IsNullOrEmpty(column.Caption))
                        column.Caption = columnTypeCollection.Keys.FirstOrDefault(x => x.ColumnName == column.ColumnName)?.Caption;
                }
            }

            foreach (var item in this.Columns)
            {
                item.Index = 0;
                this.ColumnBuilder?.Invoke(item);
                if (!item.Cancel)
                {
                    Marmat.Forms.Views.Grid.Column column = new Forms.Views.Grid.Column();
                    column.Name = item.ColumnName;
                    column.FieldName = item.ColumnName;
                    column.Caption = item.Caption;
                    column.Width = item.Width == -1 ? 100 : item.Width;
                    column.GridColumn.MinWidth = column.Width;
                    column.GridColumn.VisibleIndex = item.Index;
                    this.bGridControl1.Columns.Add(column);

                    if (this.SearchCollection.Contains(item.ColumnName) || item.IsSearch)
                    {
                        Forms.SearchControl.Field field = new Forms.SearchControl.Field();
                        field.Name = item.ColumnName;
                        field.Caption = column.Caption;
                        field.DataType = columnTypeCollection.FirstOrDefault(x => x.Key.ColumnName == item.ColumnName).Value;
                        this.searchControl1.Columns.Add(field);
                    }
                }
            }
            this.bGridControl1.DataSource = source;
        }

        /// <summary>
        /// 处理命令键
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
        {  
            int WM_KEYDOWN = 256;
            int WM_SYSKEYDOWN = 260;
            if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_SYSKEYDOWN)
            {
                switch (keyData)
                {
                    case Keys.Escape:
                        this.Close();//esc关闭窗体
                        break;
                }
            }
            return false;
        }

        private void BButton2_Click(object sender, EventArgs e)
        {
            this.FormVerify();
        }

        /// <summary>
        /// 显示窗体
        /// </summary>
        /// <param name="result">选中项</param>
        /// <returns></returns>
        bool ISelectionRecordPaginationForm<Entity, DataSource>.ShowDialog(out Entity result)
        {
            result = default;

            this.LoadData();
            bool dialog = this.ShowDialog() == DialogResult.OK;
            if (dialog)
            {
                if (this.bGridControl1.CurrentRow is DataRowView rowView)
                    result = (Entity)((object)rowView.Row);
                else
                    result = (Entity)this.bGridControl1.CurrentRow;
            }
            return dialog;
        }

        private void searchControl1_ValueChanged(object sender, EventArgs e)
        {
            this.pageControl1.LoadPage = 0;
            this.SearchData();
        }

        private void bGridControl1_RowCellDoubleClick(object sender, Forms.Views.Grid.RowColEventArgs e)
        {
            this.FormVerify();
        }

        /// <summary>
        /// 获取搜索条件
        /// </summary>
        /// <returns></returns>
        private string GetSearchCondition()
        {
            //加载数据
            string condition = this.searchControl1.Value;
            return condition;
        }

        private void textEdit1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.pageControl1.LoadPage = 0;
                this.SearchData();
            }
        }

        private void bGridControl1_CurrentChanged(object sender, Forms.Views.GridControl.GridEventArgs e)
        {
            this.bButton2.Enabled = true;
        }
        private void SearchData()
        {
            var args = new SelectionRecordFormPaginationSearchEventArgs(this.GetSearchCondition(), this.pageControl1.LoadPage);
            DataSource source = this.Search(args);
            this.pageControl1.TotalCount = args.TotalCount;
            if (source is DataTable table) table.AcceptChanges();
            this.bGridControl1.DataSource = source;
        }

        private void pageControl1_ItemClick(object sender, EventArgs e)
        {
            SearchData();
        }

        /// <summary>
        /// 验证
        /// </summary>
        private void FormVerify()
        {
            if (this.bGridControl1.CurrentRow != null)
            {
                Entity result;
                if (this.bGridControl1.CurrentRow is DataRowView rowView) result = (Entity)((object)rowView.Row);
                else result = (Entity)this.bGridControl1.CurrentRow;
                var res = Verify?.Invoke(result);
                if (res == true)
                    this.DialogResult = DialogResult.OK;
                else if (res == null)
                    this.DialogResult = DialogResult.OK;
            }
        }

        private void bGridControl1_CalcRowHeight(object sender, Forms.Views.Grid.RowHeightEventArgs e)
        {
            var args = new SelectionRecordFormItemHeightEventArgs(e.Row);
            args.ItemHeight = e.RowHeight;
            this.CalcItemHeight?.Invoke(this, args);
            e.RowHeight = args.ItemHeight;
        }

        private void bGridControl1_CustomDrawCell(object sender, Forms.Views.GridControl.RowCellCustomDrawEventArgs e)
        {
            SelectionRecordFormDrawCellEventArgs args = new SelectionRecordFormDrawCellEventArgs(e.Graphics, e.Bounds, e.Row, e.Column.FieldName, e.CellValue, () => e.DefaultDraw());
            args.DisplayText = e.DisplayText;
            this.DrawCell?.Invoke(this, args);
            e.DisplayText = args.DisplayText;

            if (!args.Handled)
                e.DefaultDraw();
        }
    }
}
